
import { isWechat, isAndroid, isIos, isApp } from '@/utils/client'
import { ref, watch, isRef, Ref, unref, nextTick, onMounted, onUnmounted, onDeactivated, onActivated } from 'vue'
import { useCopyClick } from '@/hooks'

export default function useEvent() {
  /**
   * ??
   */
  const useVisibilityEvent = (onHide?: LooseFunction, onShow?: LooseFunction) => {
    const cb = () => {
      if (document.hidden) {
        onHide?.(document.hidden)
      } else {
        onShow?.(document.hidden)
      }
    }
    window.addEventListener('visibilitychange', cb)
    return [
      () => {
        window.removeEventListener('visibilitychange', cb)
      },
    ]
  }

  /**
   * 程序初始的前置操作
   * window/document的相关事件
   */
  const mountBinds = () => {
    const { useClipboardLocal } = useCopyClick()
    /**
     * @description 1.[.back]
     * 双击页面获取当前数字人信息
     */
    useClipboardLocal(document.body)

    /**
     * @description 如果为微信内打开，监听页面是否为挂起状态，挂起超时则自动刷新
     */
    if (isWechat()) {
      const pageHidden = ref(false)
      const pageHiddenStamp = ref(null)
      const waitTimes: number = isWechat() ? 3e3 : 1e4
      useVisibilityEvent(
        (/* hidden */) => {
          pageHidden.value = true
          pageHiddenStamp.value = Date.now()
        },
        (/* visibility */) => {
          if (pageHidden.value && Date.now() - pageHiddenStamp.value > waitTimes) {
            location.reload()
          }
        },
      )
    }
    /**
     * @description 添加class
     */
    if (isApp()) {
      const classes: string[] = []
      if (isAndroid()) {
        classes.push('android')
      }
      if (isIos()) {
        classes.push('ios')
      }
      classes.forEach((className: string) => {
        document.body.classList.add(className)
        document.documentElement.classList.add(className)
      })
    }
  }

  /**
   * 输入框自动滚动至可视区
   */
  const useScrollRef = (ref: Ref<any>) => {
    if (!ref?.value) return []
    const scroll0 = () => {
      let count = 0
      const interval = setInterval(() => {
        const [root, body] = [document.documentElement, document.body]
        root.scrollTop = body.scrollTop = 0
        window.scrollTo({ top: 0 })
        root.scrollTo({ top: 0 })
        body.scrollTo({ top: 0 })
        count++
        if (count >= 40) {
          clearInterval(interval)
        }
      }, 10)
    }
    return [
      () => {
        /* scroll */
        if (isAndroid()) {
          ref.value.style.bottom = '275px'
        }
        if (isIos()) {
          ref.value.style.bottom = '300px'
        }
        scroll0()
      },
      () => {
        /* reset */
        ref.value.style.bottom = '0px'
        scroll0()
      },
    ]
  }



  return {
    useVisibilityEvent,
    mountBinds,
    useScrollRef
  }
}
const inBrowser = typeof window !== "undefined";

function onMountedOrActivated(hook) {
  let mounted;
  onMounted(() => {
    hook();
    nextTick(() => {
      mounted = true;
    });
  });
  onActivated(() => {
    if (mounted) {
      hook();
    }
  });
}

export function useEventListener(type, listener, options = {}) {
  if (!inBrowser) {
    return;
  }
  const { target = window, passive = false, capture = false } = options as any;
  let attached;
  const add = (target2) => {
    const element = unref(target2);
    if (element && !attached) {
      element.addEventListener(type, listener, {
        capture,
        passive
      });
      attached = true;
    }
  };
  const remove = (target2) => {
    const element = unref(target2);
    if (element && attached) {
      element.removeEventListener(type, listener, capture);
      attached = false;
    }
  };
  onUnmounted(() => remove(target));
  onDeactivated(() => remove(target));
  onMountedOrActivated(() => add(target));
  if (isRef(target)) {
    watch(target, (val, oldVal) => {
      remove(oldVal);
      add(val);
    });
  }
}

export const useClickAway = (target, listener, options = {}) => {
  if (!inBrowser) {
    return;
  }
  const { eventName = "click" } = options as any;
  const onClick = (event) => {
    const targets = Array.isArray(target) ? target : [target];
    const isClickAway = targets.every((item) => {
      const element = unref(item);
      return element && !element.contains(event.target);
    });
    if (isClickAway) {
      listener(event);
    }
  };
  useEventListener(eventName, onClick, { target: document });
}

const overflowScrollReg = /scroll|auto|overlay/i;
const defaultRoot = inBrowser ? window : void 0;
function isElement(node) {
  const ELEMENT_NODE_TYPE = 1;
  return node.tagName !== "HTML" && node.tagName !== "BODY" && node.nodeType === ELEMENT_NODE_TYPE;
}
function getScrollParent(el, root = defaultRoot) {
  let node = el;
  while (node && node !== root && isElement(node)) {
    const { overflowY } = window.getComputedStyle(node);
    if (overflowScrollReg.test(overflowY)) {
      return node;
    }
    node = node.parentNode;
  }
  return root;
}
export function useScrollParent(el, root = defaultRoot) {
  const scrollParent = ref();
  onMounted(() => {
    if (el.value) {
      scrollParent.value = getScrollParent(el.value, root);
    }
  });
  return scrollParent;
}